class ViewEvent {
  constructor(target, type, data) {
    this.target = target
    this.data = data
    this.type = type
    this._goon = true
    this.currentTarget = null
  }

  stopPropagation() {
    this._goon = false
  }
}
function broadcast(target, type, data, emit) {
  target.$children.forEach(child => {
    const event = new ViewEvent(child, type, data)
    child.emit_event(type, event)
    if (child.$children.length) {
      broadcast(child, type, data, emit)
    }
  })
}
export default {
  data() {
    return {
      event_observer: {}
    }
  },
  methods: {
    on_event(type, fn) {
      if (!this.event_observer[type]) {
        this.event_observer[type] = []
      }
      if (!this.event_observer[type].includes(fn)) {
        this.event_observer[type].push(fn)
      }
      return this
    },

    emit_event(type, data) {
      (this.event_observer[type] || []).forEach(fn => fn(data))
    },

    dispatch_event(type, data) {
      const event = new ViewEvent(this, type, data); let i = this
      while (i) {
        i.emit_event(type, event)
        if (event._goon) {
          i = i.$parent
        } else {
          break
        }
      }
    },
    broadcast_event(type, data) {
      broadcast(this, type, data, this.emit_event)
    }
  }
}
